import threading
import server
from poker_dealing import *
from time import sleep
from HeartGame_server import HeartGame_server

class main_server:
    '''
    可以调用send_message_through_server_to_client()和send_message_throuth_server_to_all()向客户端发送消息
    接收到消息之后会自动调用handle_message()函数
    '''

    '''
    与客户端的通信格式：
    msg = {
        "type": "notification"/"other player's cards"/... 消息类型
        "content": 消息内容    
    }
    '''
    def __init__(self, host='::', port=65432):
        self.game = HeartGame_server() #用于处理各种服务器端的游戏逻辑

        self.rooms_id = [] #记录所有的房间号，房间号为字符串
        self.rooms_status = {}
        self.client_position_around_talbe = {} # 记录玩家在桌上的位置，分别为0~3
        '''
        self.rooms_status:
        记录所有房间的状态，格式为
            self.rooms_status[room_id] = {
                "player_num": n 玩家人数
                "players": [] 列表元素为所有房间内玩家的client_id
                "playing": True/False 是否正在进行游戏
            }
        '''
        self.client_in_room_id = {}#记录客户端在哪个房间中

        self.clients_id_to_id_txt = {} #记录client的id到id_txt的对应关系，格式为{id :id_txt}

        self.lock = threading.Lock()

        #定义获取新消息事件
        self.new_msg_from_server_event = threading.Event()

        #客户端server
        self.server = server.server(get_message_from_server=self.get_message_from_server, host=host, port=port)



        #启动服务器，必须放在__init__的最后一行
        self.server.start()
    
    def get_message_from_server(self, msg, client_id):#从server获得消息
        print('get message')
        self.handle_message(msg=msg, client_id=client_id)


    def send_message_through_server_to_client(self, msg, client_id):#用server向指定客户端发送消息
        if isinstance(client_id, list):
            for c_id in client_id:
                self.server.send_message_to_client(msg, c_id)
        else:
            self.server.send_message_to_client(msg, client_id)

    def send_message_throuth_server_to_all(self, msg):#用server向所有客户端发送消息
        self.server.send_message_to_all(msg)

    def send_message_through_server_to_all_except_client_id(self, msg, client_id):#用server向处指定客户端外的所有客户端发送消息
        if isinstance(client_id, list):
            for c in self.server.clients:
                if c["id"] not in client_id:
                    self.server.send_message_to_client(msg, c["id"])
        else:
            for c in self.server.clients:
                if c["id"] != client_id:
                    self.server.send_message_to_client(msg, c["id"])



    def handle_message(self, msg, client_id):
        '''需要补充'''
        print(f'接收到来自{client_id}的消息{msg}，正在处理')
        if msg["type"] == "message":
            msg = {
                "type": "message",
                "content": {
                    "client_id_txt": self.clients_id_to_id_txt[client_id], 
                    "msg": msg["content"]
                }
            }
            self.send_message_through_server_to_all_except_client_id(msg=msg, client_id=client_id)
            print(f'已发送来自{client_id}的消息至所有客户端')
            print(f'消息为{msg}')

        elif msg["type"] == "id_txt":
            self.add_client_id_txt(client_id, msg["content"])
            self.send_client_id_to_client(client_id)

        elif msg["type"] == "entering room request":
            print('handling entering room request')
            self.handle_entering_room_request(client_id=client_id, room_id=msg["content"])

        elif msg["type"] == "card":
            print(f'have got card from{client_id}, start to handle it.')
            self.handle_player_card(msg["content"], client_id)

    def add_client_id_txt(self, client_id, client_id_txt): #添加client_id和client_id_txt的对应关系
        with self.lock:
            self.clients_id_to_id_txt[client_id] = client_id_txt

    def send_client_id_to_client(self, client_id):
        msg = {
            "type": "client_id",
            "content": client_id
        }
        self.send_message_through_server_to_client(client_id=client_id, msg=msg)

    def send_txt_id_to_all(self, room_id):
        players_id = self.rooms_status[room_id]["players"] #获得房间内所有的玩家id
        txt_ids = ["", "", "", ""]
        for player_id in players_id:
            txt_ids[int(self.client_position_around_talbe[player_id])] = self.clients_id_to_id_txt[player_id]
        msg = {
            "type": "txt_id",
            "content": txt_ids
        }
        players_id = self.rooms_status[room_id]["players"] #获得房间内所有的玩家id
        self.send_message_through_server_to_client(msg=msg, client_id=players_id)

    def handle_entering_room_request(self, client_id, room_id):
        if room_id not in self.rooms_id: #无此房间则新建房间
            self.create_new_room(room_id)
        if self.rooms_status[room_id]["player_num"] >= 4: #房间人满就拒绝加入请求
            self.notify_entering_room_denied(client_id)
        else: #人数未满，允许加入
            self.client_position_around_talbe[client_id] = self.rooms_status[room_id]["player_num"]
            self.rooms_status[room_id]["player_num"] += 1
            self.rooms_status[room_id]["players"].append(client_id)
            self.client_in_room_id[client_id] = room_id
            self.notify_entering_room_allowed(client_id)
            print(f'have added new player into room {room_id}.')
            print('current room status:')
            print(f'players:{self.rooms_status}')

            self.send_player_positions(room_id)
            print(f'player num:{self.rooms_status[room_id]["player_num"]}')
            self.send_txt_id_to_all(self.client_in_room_id[client_id])
            if self.rooms_status[room_id]["player_num"] == 4:
                self.start_game(room_id)

    def handle_player_card(self, card, client_id): #处理玩家打出的牌，将一个玩家打出的牌发送给所有玩家，并使用HeartGame_server处理
        #将打出的牌发送给所有玩家
        msg = {
            "type": "other player's card",
            "content": {
                'from': client_id,
                'card': card
            }
        }
        room_id = self.client_in_room_id[client_id] #获得玩家所处的房间
        players_id = self.rooms_status[room_id]["players"] #获得房间内所有的玩家id
        self.send_message_through_server_to_client(msg=msg, client_id=players_id)
        print(f'have sent card from {client_id} to all')

        #用HeartGame_server处理
        self.game.cards_in_round[self.client_position_around_talbe[client_id]] = card #将牌添加到本轮打出的牌中
        print(self.game.cards_in_round, self.game.current_round)
        if None not in self.game.cards_in_round: #如果四名玩家都出过牌了，就结算本轮
            position, score = self.game.judge_largest_card() #出牌最大的玩家的座位号和分数
            print('the player get score:')
            print(position, score)
            ''' self.game.game_scores[position] += score 
            msg = {
                "type": "player with largest card",
                "content": {
                    "position": position,
                    "score": score
                }
            }
            self.send_message_through_server_to_client(msg=msg, client_id=players_id)'''
            print(self.game.game_scores)
            self.game.game_scores[position] += score
            print(self.game.game_scores)

            
            self.game.reset_cards_in_round() #重置本轮打出的牌

            if self.game.current_round == 13: #所有玩家已经出完了牌
                msg = self.game.end_game()
                self.send_message_through_server_to_client(msg=msg, client_id=players_id)
                self.start_game(room_id=room_id)
                return
            
            self.send_players_score(position, score, players_id)
            self.game.current_round += 1
            self.game.first_player = position #更新下一轮第一个出牌的玩家
            self.send_first_player(first=position, room_id=room_id)

    def create_new_room(self, room_id): #创建房间号为room_id的房间
        self.rooms_id.append(room_id)
        self.rooms_status[room_id] = {
            "player_num": 0,
            "players": [],
            "playing": False
        }

    def notify_entering_room_denied(self, client_id): #通知：拒绝加入房间申请
        msg = {
            "type": "notification",
            "content": "entering room denied"
        }
        self.send_message_through_server_to_client(msg=msg, client_id=client_id)

    def notify_entering_room_allowed(self, client_id): #通知：同意加入房间申请
        msg = {
            "type": "notification",
            "content": "entering room allowed"
        }
        self.send_message_through_server_to_client(msg=msg, client_id=client_id)
    
    def send_player_positions(self, room_id): #向所有玩家发送各玩家的位置
        players_id = self.rooms_status[room_id]["players"]
        positions = {}
        for player in players_id:
            print(player)
            positions[player] = self.client_position_around_talbe[player]
        #print(positions)
        msg = {
            "type": "players' positions",
            "content": positions
        }
        #print(msg)
        self.send_message_through_server_to_client(msg=msg, client_id=players_id)
        print(f'have sent players\' positions to {players_id}')
    
    def start_game(self, room_id): #洗牌发牌，并将手牌和第一个出牌的玩家发送给所有玩家
        hands, first = deal_poker()
        '''hands = [("♥","2"), ("♥", "3"), ("♥","4"), ("♥","5")]
        first = 0'''
        self.game.first_player = first
        self.send_players_cards(hands, room_id)
        self.send_first_player(first, room_id)
        self.game.current_round = 1

    def send_players_cards(self, hands, room_id): #将手牌发送给房间中的四名玩家
        for i, client_id in enumerate(self.rooms_status[room_id]["players"]):
            msg = {
                "type": "send hand",
                "content": hands[i]
            }
            self.send_message_through_server_to_client(msg=msg, client_id=client_id)
            #print(f'have sent {hands[i]} to {client_id}')

    def send_first_player(self, first, room_id):# 将第一个出牌的玩家编号发送给所有玩家
        msg = {
            "type": "first player",
            "content": first
        }
        players_id = self.rooms_status[room_id]["players"]
        self.send_message_through_server_to_client(msg=msg, client_id=players_id)
        print(f'have sent the first player to {players_id}')

    def send_players_score(self, position, score, client_id):
        msg = {
            "type": "get score",
            "content": {
                "position": position,
                "score": score
            }
        }
        self.send_message_through_server_to_client(msg=msg, client_id=client_id)
if __name__ == "__main__":
    main_server = main_server()